package com.wusiwei.controller;

import com.wusiwei.entity.User;
import com.wusiwei.security.AuthResponse;
import com.wusiwei.security.ErrorResponse;
import com.wusiwei.security.JwtTokenUtil;
import com.wusiwei.security.LoginRequest;
import com.wusiwei.service.UserService;
import com.wusiwei.vo.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.*;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 认证控制器
 * 处理登录、注销等身份认证相关的API
 */
@RestController
@RequestMapping("/api/auth")
@Tag(name = "身份认证", description = "用户登录、注销、获取信息等认证相关API")
public class AuthController {

    private static final Logger logger = LoggerFactory.getLogger(AuthController.class);

    @Autowired
    private UserService userService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    /**
     * 用户登录
     *
     * @param loginRequest 登录请求
     * @return 登录结果，包含用户token
     */
    @PostMapping("/login")
    @Operation(summary = "用户登录", description = "用户登录并获取JWT令牌")
    public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
        logger.info("登录请求: {}", loginRequest.getUsername());
        // 参数校验
        if (loginRequest == null || loginRequest.getUsername() == null || loginRequest.getUsername().isEmpty()
                || loginRequest.getPassword() == null || loginRequest.getPassword().isEmpty()) {
            logger.error("登录失败: 用户名或密码为空");
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body(new ErrorResponse("用户名和密码不能为空"));
        }
        try {
            authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            loginRequest.getUsername(),
                            loginRequest.getPassword()
                    )
            );
            final UserDetails userDetails = userDetailsService.loadUserByUsername(loginRequest.getUsername());
            final String token = jwtTokenUtil.generateToken(userDetails);
            return ResponseEntity.ok(new AuthResponse(token));
        } catch (BadCredentialsException e) {
            logger.error("登录失败: 用户名或密码错误 {}", e.getMessage());
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                    .body(new ErrorResponse("用户名或密码错误"));
        } catch (Exception e) {
            logger.error("登录异常: {}", e.getMessage(), e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(new ErrorResponse("登录时发生错误: " + e.getMessage()));
        }
    }

    /**
     * 获取当前用户信息
     */
    @GetMapping("/info")
    public Result<Map<String, Object>> getUserInfo(Authentication authentication) {
        logger.info("获取用户信息: {}", authentication);
        if (authentication == null || !authentication.isAuthenticated()) {
            return Result.error("未登录或授权已过期");
        }

        // 获取用户名
        String username = authentication.getName();

        // 查询用户信息
        User user = userService.findByUsername(username);
        if (user == null) {
            return Result.error("用户不存在");
        }
        // 构建用户信息
        Map<String, Object> userInfo = new HashMap<>();
        userInfo.put("id", user.getId());
        userInfo.put("username", user.getUsername());
        userInfo.put("realName", user.getRealName());
        userInfo.put("email", user.getEmail());
        userInfo.put("phone", user.getPhone());
        // 获取用户角色
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        List<String> roles = authorities.stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.toList());
        userInfo.put("roles", roles);
        return Result.success(userInfo);
    }

    /**
     * 用户注销
     *
     * @return 注销结果
     */
    @Operation(summary = "用户注销", description = "当前用户注销登录")
    @PostMapping("/logout")
    public Result<Void> logout() {
        // 由于使用JWT，服务端不需要处理注销，前端只需要删除本地存储的token即可
        return Result.success();
    }

    /**
     * 修改密码
     *
     * @param passwordRequest 密码修改请求，包含旧密码和新密码
     * @return 修改结果
     */
    @Operation(summary = "修改密码", description = "修改当前用户的登录密码")
    @PostMapping("/changePassword")
    public Result<Void> changePassword(
            @RequestHeader(value = "Authorization") String token,
            @RequestBody Map<String, String> passwordRequest) {
        // 获取当前用户名
        String username;
        try {
            username = jwtTokenUtil.getUsernameFromToken(token.substring(7));
        } catch (Exception e) {
            logger.error("解析令牌错误", e);
            return Result.error(401, "无效的令牌");
        }
        String oldPassword = passwordRequest.get("oldPassword");
        String newPassword = passwordRequest.get("newPassword");

        if (oldPassword == null || newPassword == null) {
            return Result.error(400, "旧密码和新密码不能为空");
        }
        // 修改密码
        boolean success = userService.changePassword(username, oldPassword, newPassword);
        if (!success) {
            return Result.error(401, "旧密码错误");
        }
        return Result.success();
    }

    /**
     * 刷新令牌
     *
     * @param token 当前令牌
     * @return 刷新后的令牌
     */
    @Operation(summary = "刷新令牌", description = "刷新当前用户的JWT令牌")
    @PostMapping("/refreshToken")
    public ResponseEntity<?> refreshToken(@RequestHeader(value = "Authorization") String tokenHeader) {
        logger.info("刷新令牌请求");
        // 检查令牌头是否存在
        if (tokenHeader == null || !tokenHeader.startsWith("Bearer ")) {
            logger.error("刷新令牌失败: 无效的令牌格式");
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                    .body(new ErrorResponse("无效的令牌格式"));
        }
        // 提取令牌
        String token = tokenHeader.substring(7);
        try {
            // 验证令牌有效性
            if (!jwtTokenUtil.validateToken(token)) {
                logger.error("刷新令牌失败: 令牌已过期或无效");
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                        .body(new ErrorResponse("令牌已过期或无效"));
            }
            // 刷新令牌
            String refreshedToken = jwtTokenUtil.refreshToken(token);
            // 如果令牌未刷新（没有达到刷新条件），返回原令牌
            if (refreshedToken == null) {
                logger.error("刷新令牌失败: 未知错误");
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                        .body(new ErrorResponse("刷新令牌时发生错误"));
            }
            logger.info("令牌刷新成功");
            return ResponseEntity.ok(new AuthResponse(refreshedToken));
        } catch (Exception e) {
            logger.error("刷新令牌异常: {}", e.getMessage(), e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(new ErrorResponse("刷新令牌时发生错误: " + e.getMessage()));
        }
    }
} 